#define _CRT_SECURE_NO_WARNINGS

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>

#include "bmpFile.h"


void Rgb_to_Gry_without_LUT(BYTE *pRgbImg, int width, int height, BYTE *pGryImg)
{
	BYTE *pRgbEnd, *pRgbCur;
	BYTE *pGryCur;
	pRgbEnd = pRgbImg + width * height * 3;
	clock_t t1 = clock();
	for (int i = 1; i <= 1000; i++)
	{
		pGryCur = pGryImg;
		for (pRgbCur = pRgbImg; pRgbCur < pRgbEnd; pRgbCur += 3)
		{
			*(pGryCur++) = 0.299 * (*pRgbCur) + 0.587 * (*(pRgbCur + 1)) + 0.114 *  (*(pRgbCur + 2));
		}
	}
	clock_t t2 = clock();
	printf("1000 times Rgb_to_Gry without LUT takes %d ms\n", t2 - t1);
	return;
}

void Rgb_to_Gry_with_LUT(BYTE *pRgbImg, int width, int height, BYTE *pGryImg)
{
	BYTE *pRgbEnd, *pRgbCur;
	BYTE *pGryCur;
	pRgbEnd = pRgbImg + width * height * 3;
	clock_t t1 = clock();
	float R[256], G[256], B[256];
	for (int i = 0; i <= 255; i++) {
		R[i] = 0.299 * i;
		G[i] = 0.587 * i;
		B[i] = 0.114 * i;
	}
	for (int i = 1; i <= 1000; i++)
	{
		pGryCur = pGryImg;
		for (pRgbCur = pRgbImg; pRgbCur < pRgbEnd; pRgbCur += 3)
		{
			*(pGryCur++) = R[*pRgbCur] + G[*(pRgbCur + 1)] + B[*(pRgbCur + 2)];
		}
	}
	clock_t t2 = clock();
	printf("1000 times Rgb_to_Gry with LUT takes %d ms\n", t2 - t1);
	return;
}

void Gry_AVS(BYTE *pGryImg, int width, int height)
{
	BYTE *pGryEnd, *pGryCur;
	pGryEnd = pGryImg + width * height;
	float b1, b2, c1, c2, k, b, s;
	for (pGryCur = pGryImg, s = 0; pGryCur < pGryEnd; )
	{
		s += *(pGryCur++);
	}
	b1 = s / (width * height);
	for (pGryCur = pGryImg, s = 0; pGryCur < pGryEnd; )
	{
		s += pow(*(pGryCur++) - b1, 2);
	}
	c1 = pow(s / (width * height - 1), 0.5);
	printf("%f %f\n", b1, c1);
	b2 = 40.0; c2 = 20.0;
	//b2 = 100.0; c2 = 80.0;
	//b2 = 140.0; c2 = 100.0;
	k = c2 / c1;
	b = b2 - k * b1;
	int LUT[256];
	for (int i = 0; i < 256; i++) 
	{
		LUT[i] = max(0, min(255, i * k + b));
	}
	for (pGryCur = pGryImg; pGryCur < pGryEnd; )
	{
		*(pGryCur++) = LUT[*(pGryCur)];
	}
	return;
}

void Histogram_Equalize(BYTE *pGryImg, int width, int height) 
{
	int histogram[256], LUT[256], A, g, S = width * height;
	BYTE *pCur, *pEnd = pGryImg + S;
	memset(histogram, 0, sizeof(int) * 256);
	for (pCur = pGryImg; pCur < pEnd; ) histogram[*(pCur++)]++;
	A = histogram[0];
	LUT[0] = 255 * A / S;
	for (g = 1; g < 256; g++)
	{
		A += histogram[g];
		LUT[g] = 255 * A / S;
	}
	for (pCur = pGryImg; pCur < pEnd; ) *(pCur++) = LUT[*pCur];
	return;
}

void Histogram_Equalize_14bit(short int *p14bitImg, int width, int height, BYTE *pGryImg)
{
	int histogram[1 << 14], A, LUT[1 << 14], S = width * height;
	memset(histogram, 0, sizeof(int)*(1 << 14));
	for (int i = 0; i < width * height; i++)histogram[*(p14bitImg + i)]++;
	A = histogram[0];
	LUT[0] = 255 * A / S;
	for (int i = 1; i < (1 << 14); i++)
	{
		A += histogram[i];
		LUT[i] = 255 * A / S;
	}
	for (int i = 0; i < width * height; i++) *(pGryImg + i) = LUT[*(p14bitImg + i)];
	return;
}

int main()
{


	int width, height;
	BYTE *pGryImg;
	BYTE *pRgbImg;
	short int *p14bitImg;

	pGryImg = Rmw_Read8BitBmpFile2Img("..\\DIP_wy_02\\0201Gry.bmp", &width, &height);
	Gry_AVS(pGryImg, width, height);
	Rmw_Write8BitImg2BmpFile(pGryImg, width, height, "..\\DIP_wy_02\\0201Gry_AVS1111.bmp");
	/*
	pRgbImg = Rmw_Read24BitBmpFile2Img("..\\DIP_wy_02\\0201Rgb.bmp", &width, &height);
	pGryImg = new BYTE[width * height];
	Rgb_to_Gry_without_LUT(pRgbImg, width, height, pGryImg);
	Rmw_Write8BitImg2BmpFile(pGryImg, width, height, "..\\DIP_wy_02\\0201Gry_without_LUT.bmp");

	pRgbImg = Rmw_Read24BitBmpFile2Img("..\\DIP_wy_02\\0201Rgb.bmp", &width, &height);
	pGryImg = new BYTE[width * height];
	Rgb_to_Gry_with_LUT(pRgbImg, width, height, pGryImg);
	Rmw_Write8BitImg2BmpFile(pGryImg, width, height, "..\\DIP_wy_02\\0201Gry_with_LUT.bmp");

	pGryImg = Rmw_Read8BitBmpFile2Img("..\\DIP_wy_02\\0202Plane.bmp", &width, &height);
	Histogram_Equalize(pGryImg, width, height);
	Rmw_Write8BitImg2BmpFile(pGryImg, width, height, "..\\DIP_wy_02\\0202Plane_Res.bmp");

	pGryImg = Rmw_Read8BitBmpFile2Img("..\\DIP_wy_02\\0203Girl.bmp", &width, &height);
	Histogram_Equalize(pGryImg, width, height);
	Rmw_Write8BitImg2BmpFile(pGryImg, width, height, "..\\DIP_wy_02\\0203Girl_Res.bmp");

	pRgbImg = Rmw_Read24BitBmpFile2Img("..\\DIP_wy_02\\0201Rgb.bmp", &width, &height);
	Histogram_Equalize(pRgbImg, width * 3, height);
	Rmw_Write24BitImg2BmpFile(pRgbImg, width, height, "..\\DIP_wy_02\\0201Rgb_Res.bmp");

	width = 640; height = 480;
	p14bitImg = new short int[width * height];
	pGryImg = new BYTE[width * height];
	FILE *fp = fopen("..\\DIP_wy_02\\0204IR14bit.raw", "rb");
	fread(p14bitImg, sizeof(short int), width * height, fp);
	fclose(fp);
	Histogram_Equalize_14bit(p14bitImg, width, height, pGryImg);
	Rmw_Write8BitImg2BmpFile(pGryImg, width, height, "..\\DIP_wy_02\\0204IR24BIT_res.bmp");

*/

	printf("Press any key to exit!\n");
	getchar();
	return 0;
}
